/**
 * Created with CLion.
 * Description: 
 * User: loong
 * Date: 2024/9/2
 * Time: 21:31
 */

#include "GroupService.h"
#include "Group.pb.h"
#include <DataHandle.h>

//TODO 考虑多用户同时操作的可能性 -> 用redis分布式锁？

void GroupService::SetDataHandle(const IDataHandleSPtr &handle)
{
    handle_ = handle;
}

grpc::Status GroupService::SearchGroup(grpc::ServerContext * context, const Chat::SearchGroupRequest * request, Chat::SearchGroupReply * response)
{
    auto ret = handle_->FindGroupWithNameLike(request->group_name());
    for (const auto & info : ret) {
        response->mutable_group_info()->insert({info->id, info->name});
    }

    return grpc::Status::OK;
}

grpc::Status GroupService::CreateGroup(grpc::ServerContext * context, const Chat::CreateGroupRequest * request, Chat::CreateGroupReply * response)
{
    //TODO 群组码生成，暂时用静态变量替代
    static int group_id = 10000;

    // 创建群组
    auto group_info = std::make_shared<GroupInfo>();
    group_info->name = request->group_name();
    group_info->id = request->group_id();

    bool ret = handle_->AddGroup(group_info);
    if(!ret)
        return {grpc::StatusCode::ABORTED, "Group create fail!"};

    // 增加参加者
    //TODO request中的创建者ID应根据context中客户端元数据进行验证，确保创建者ID与客户端ID一致；验证成功后填写创建者名称。
    // auto metadata = context->client_metadata();

    auto creator_id = request->creator_id();

    ret = handle_->JoinGroup(group_info->id,creator_id);
    if(!ret)
        return {grpc::StatusCode::ABORTED,"Group join fail!"};

    // 修改user权限
    ret = handle_->ModifyGroupMemberRole(group_info->id,creator_id,GroupInfo::Creator);
    if(!ret)
        return {grpc::StatusCode::ABORTED,"Modify role fail!"};


    response->set_group_id(group_info->id);

    return grpc::Status::OK;

    auto ParseTokenAndGetUserId = [=](const std::string & token)->std::string {
        std::string tag = "<Token>";
        auto ret = token.find(tag);

        if (ret != std::string::npos) {
            std::string client_id = token.substr(ret + tag.length());
            return client_id;
        }

        return std::string();
    };
}

grpc::Status GroupService::JoinGroup(grpc::ServerContext * context, const Chat::JoinGroupRequest * request, Chat::CommonGroupReply * response)
{
    bool ret = handle_->JoinGroup(request->group_id(),request->user_id());
    if(!ret)
        return {grpc::StatusCode::ABORTED,"Group join fail!"};

    response->set_message("欢迎加入: " + request->group_id());

    return grpc::Status::OK;
}

grpc::Status GroupService::InviteJoinGroup(grpc::ServerContext * context, const Chat::InviteJoinGroupRequest * request, Chat::CommonGroupReply * response)
{
    bool ret = handle_->MemberIsExist(request->group_id(),request->invite_id());
    if(ret)
        return {grpc::StatusCode::CANCELLED,"User is already in group!"};

    ret = handle_->JoinGroup(request->group_id(),request->user_id());
    if(!ret)
        return {grpc::StatusCode::ABORTED,"Invite join group fail!"};

    response->set_message("欢迎加入: " + request->group_id());
    return grpc::Status::OK;
}

grpc::Status GroupService::ExitGroup(grpc::ServerContext * context, const Chat::ExitGroupRequest * request, Chat::CommonGroupReply * response)
{
    bool ret = handle_->MemberIsExist(request->group_id(),request->user_id());
    if(!ret)
        return {grpc::StatusCode::NOT_FOUND,"User is not in group"};

    ret = handle_->ExitGroup(request->group_id(),request->user_id());
    if(!ret)
        return {grpc::StatusCode::ABORTED,"Group exit fail!"};

    response->set_message("Group exit successful!");
    return grpc::Status::OK;
}

grpc::Status GroupService::KickOut(grpc::ServerContext * context, const Chat::KickOutRequest * request, Chat::CommonGroupReply * response)
{
    bool ret = handle_->MemberIsExist(request->group_id(),request->user_id());
    if(!ret)
        return {grpc::StatusCode::NOT_FOUND,"User is not in group"};

    ret = handle_->ExitGroup(request->group_id(),request->user_id());
    if(!ret)
        return {grpc::StatusCode::ABORTED,"KickOut fail!"};

    response->set_message(request->user_id() + " KickOut successful!");
    return grpc::Status::OK;
}

grpc::Status GroupService::DisbandGroup(grpc::ServerContext * context, const Chat::DisbandGroupRequest * request, Chat::CommonGroupReply * response)
{
    bool ret = handle_->MemberIsExist(request->group_id(),request->user_id());
    if(!ret)
        return {grpc::StatusCode::NOT_FOUND,"User is not in group"};

    auto type = handle_->UserType(request->group_id(),request->user_id());
    if(type != GroupInfo::Creator)
        return {grpc::StatusCode::ABORTED,"User is not creator"};

    auto members = handle_->Members(request->group_id());

    //情况组成员
    for(auto & member : members) {
        handle_->ExitGroup(request->group_id(),member->id);
    }

    ret = handle_->RemoveGroup(request->group_id());
    if(!ret)
        return {grpc::StatusCode::ABORTED,"Group disband fail!"};

    response->set_message("Group disband successful!");
    return grpc::Status::OK;
}